//
// Created by hjie on 23-6-3.
//
#include "message_attr.h"
#include <zlib.h>
#include "stun_message.h"
#include <cstring>
#include <string>
#include <cstdint>
#include <cstdlib>
#include <unistd.h>
#include "write_buffer.h"
#include <arpa/inet.h>

void TestMessageAttr()
{
    // bind request response message
    // std::string content = "0101000c2112a44251634b4e6331786c78335a7a00200008000199611c93c177";
    // std::string content =  "000300102112a4425ac8258ee5e100648de32dd6001900041100000080280004284eb56a";
    // std::string content = "000100082112a44236376336363937333531666680280004e6f299db";
    std::string content = "000300602112a442a4d175f73de447c0ec621aa5001900041100000000060004757365720014000770696f6e2e6c790000150020316431653361613032646666343139383937656565383138626164386430623700080014a40d350d5a8ec933b5b8391313188032df59b6c880280004ea1981a0";

    uint8_t * data = new uint8_t [content.size()/2];
    int index = 0;
    for (int i = 0; i < content.size(); i+=2)
    {
        char tmp[5] = {0};
        snprintf(tmp, 3, "%s", content.substr(i, 2).c_str());
        data[index++] = strtol(tmp, NULL, 16);
    }
    for (int i = 0; i < content.size()/2; i++)
    {
        printf("%02x ", data[i]);
    }
    printf("\n");

    UdpBufferPacket packet;
    packet.buffer = new DataBuffer(0);
    packet.buffer->PushDataBuffer(data, content.size()/2);


    uLong crc = crc32(0L, Z_NULL, 0);
    crc = crc32(crc, (const Bytef*)packet.buffer->Data(), packet.buffer->Length() - 8);

    printf("check crc 32 data : %8lx and %8lx and length : %d.\n", crc, (crc ^ 0x5354554E), packet.buffer->Length());

    StunMessage message;
    int use_length = 0;
    ParseStatus status = message.ParseStunMessage(&packet, use_length);

    if (status == EmParseFinishStatus)
    {
        printf("parse finish attr size : %ld!\n", message.m_attr_map.size());
    }

    auto crc32_iter = message.m_attr_map.find(EmFingerPrint);
}

void TestXorAddress()
{
    uint8_t data [] = {0x00,0x20,0x00,0x08,0x00,0x01,0x99,0x61,0x1c,0x93,0xc1,0x77};
    int use_length = 0;
    auto attr = MessageAttr::ProcessMessageAttr((const uint8_t*)data, 12, use_length);
    if (attr)
    {
        WriteBuffer buffer;
        attr->ComposeAttr(buffer);
        uint8_t * array = buffer.Data();
        size_t length = buffer.Length();
        for (int i = 0; i < length; i++)
        {
            printf("%02x ", array[i]);
        }
    }
    printf("\n");
}

void TestXorAddr()
{
    struct sockaddr_in sai;
    memset(&sai,0, sizeof(sai));
    sai.sin_family = AF_INET;
    sai.sin_port = htons(11676);
    inet_pton(AF_INET, "61.129.101.71", &sai.sin_addr);

    AttrXorMappedAddress * address = new AttrXorMappedAddress();
    address->ParseAddrInfo(IPPROTO_IP, (struct sockaddr*)&sai, sizeof(sai));

    printf("encoder port : %x.\n", address->LocalPort());
    printf("decoder port : %d.\n", address->DecoderPort());
    printf("addr : %.8x.\n", address->EncoderAddr());
    printf("addr : %s.\n", address->DecoderAddr().c_str());
}

int main()
{
    //TestXorAddress();
    // TestXorAddr();
    TestMessageAttr();
    return EXIT_SUCCESS;
}
